package cn.iocoder.yudao.module.trade.order.service;

import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.api.trade.delivery.dto.ExpressTrackRespDTO;
import cn.iocoder.yudao.module.api.trade.order.dto.TradeOrderQueryDTO;
import cn.iocoder.yudao.module.api.trade.order.enums.TradeOrderTypeEnum;
import cn.iocoder.yudao.module.api.trade.order.vo.AppTradeOrderPageVO;
import cn.iocoder.yudao.module.trade.order.dal.dataobject.TradeOrderDO;
import cn.iocoder.yudao.module.trade.order.dal.dataobject.TradeOrderItemDO;
import cn.iocoder.yudao.module.trade.order.vo.TradeOrderPageForVerifyReqVO;
import cn.iocoder.yudao.module.trade.order.vo.TradeOrderPageReqVO;
import cn.iocoder.yudao.module.trade.order.vo.TradeOrderSummaryRespVO;
import jakarta.annotation.Nullable;

import java.util.Collection;
import java.util.List;

import static java.util.Collections.singleton;

/**
 * 交易订单【读】 Service 实现类
 *
 * @author 芋道源码
 */
public interface TradeOrderQueryService {

    /**
     * 获得指定编号的交易订单
     *
     * @param id 交易订单编号
     * @return 交易订单
     */
    TradeOrderDO getOrder(Long id);

    /**
     * 获得指定用户，指定的交易订单
     *
     * @param no     交易单号
     * @return 交易订单
     */
    TradeOrderDO getOrderByNo(String no);

    /**
     * 获得指定用户，指定的交易订单
     *
     * @param userId 用户编号
     * @param id     订单编号
     * @return 交易订单
     */
    TradeOrderDO getOrder(Long userId, Long id);

    /**
     * 获得指定用户，指定的交易订单
     *
     * @param userId 用户编号
     * @param no     交易单号
     * @return 交易订单
     */
    TradeOrderDO getOrderByNo(Long userId, String no);

    /**
     * 获得指定用户，指定活动，指定状态的交易订单
     *
     * @param userId                用户编号
     * @param combinationActivityId 活动编号
     * @param status                订单状态
     * @return 交易订单
     */
    TradeOrderDO getOrderByUserIdAndStatusAndCombination(Long userId, Long combinationActivityId, Integer status);

    /**
     * 获得订单列表
     *
     * @param ids 订单编号数组
     * @return 订单列表
     */
    List<TradeOrderDO> getOrderList(Collection<Long> ids);

    /**
     * 【管理员】获得交易订单分页
     *
     * @param reqVO 分页请求
     * @return 交易订单
     */
    PageResult<TradeOrderDO> getOrderPage(TradeOrderPageReqVO reqVO);

    /**
     * 【管理员】获得交易订单分页
     *
     * @param reqVO 分页请求
     * @return 交易订单
     */
    PageResult<TradeOrderDO> getOrderPageForVerify(TradeOrderPageForVerifyReqVO reqVO);

    /**
     * 【管理员】获得订单统计
     *
     * @param reqVO 请求参数
     * @return 订单统计
     */
    TradeOrderSummaryRespVO getOrderSummary(TradeOrderPageReqVO reqVO);

    /**
     * 【商家】获得交易订单分页
     *
     * @param shopId 店铺编号
     * @return 交易订单
     */
    PageResult<TradeOrderDO> getOrderPageByShopId(Long shopId, PageParam pageParam, TradeOrderQueryDTO queryDTO);

    /**
     * 【配送员】获得交易订单分页
     *
     * @param shopId 店铺编号
     * @param staffId 店铺员工编号
     * @return 交易订单
     */
    PageResult<TradeOrderDO> getOrderPageByStaffId(Long shopId, Long staffId, PageParam pageParam, Integer dineStatus);

    /**
     * 【商家】获得交易订单数量
     *
     * @param shopId 店铺编号
     * @param status        订单状态。如果为空，则不进行筛选
     * @param commentStatus 评价状态。如果为空，则不进行筛选
     * @return 订单数量
     */
    Integer getOrderCountByShopId(Long shopId, Integer status, Boolean commentStatus);

    /**
     * 【用户】获得交易订单分页
     *
     * @param userId 用户编号
     * @return 交易订单
     */
    PageResult<TradeOrderDO> getOrderPageByUserId(Long userId, PageParam pageParam, TradeOrderQueryDTO queryDTO);

    /**
     * 【用户】获得交易订单数量
     *
     * @param userId       用户编号
     * @param deliveryTypes       配送类型/服务方式
     * @param status       订单状态。如果为空，则不进行筛选
     * @param commonStatus 评价状态。如果为空，则不进行筛选
     * @return 订单数量
     */
    Integer getOrderCountByUserId(Long userId, List<Integer> deliveryTypes, Integer status, Boolean commonStatus);

    /**
     * 【配送员】获得交易订单数量
     *
     * @param shopId       店铺编号
     * @param staffId       配送人员编号
     * @param dineStatus       点餐状态。如果为空，则不进行筛选
     * @return 订单数量
     */
    Integer getOrderCountByStaffId(Long shopId, Long staffId, @Nullable Integer ...dineStatus);

    /**
     * 【前台】获得订单的物流轨迹
     *
     * @param id     订单编号
     * @param userId 用户编号
     * @return 物流轨迹数组
     */
    List<ExpressTrackRespDTO> getExpressTrackList(Long id, Long userId);

    /**
     * 【后台】获得订单的物流轨迹
     *
     * @param id 订单编号
     * @return 物流轨迹数组
     */
    List<ExpressTrackRespDTO> getExpressTrackList(Long id);

    /**
     * 【会员】在指定活动下，用户购买的商品数量
     *
     * @param userId     用户编号
     * @param activityId 活动编号
     * @param type       订单类型
     * @return 活动商品数量
     */
    int getActivityProductCount(Long userId, Long activityId, TradeOrderTypeEnum type);

    // =================== Order Item ===================

    /**
     * 获得指定用户，指定的交易订单项
     *
     * @param userId 用户编号
     * @param itemId 交易订单项编号
     * @return 交易订单项
     */
    TradeOrderItemDO getOrderItem(Long userId, Long itemId);

    /**
     * 获得交易订单项
     *
     * @param id 交易订单项编号 itemId
     * @return 交易订单项
     */
    TradeOrderItemDO getOrderItem(Long id);

    /**
     * 根据交易订单编号，查询交易订单项
     *
     * @param orderId 交易订单编号
     * @return 交易订单项数组
     */
    default List<TradeOrderItemDO> getOrderItemListByOrderId(Long orderId) {
        return getOrderItemListByOrderIds(singleton(orderId));
    }

    /**
     * 根据交易订单编号数组，查询交易订单项
     *
     * @param orderIds 交易订单编号数组
     * @return 交易订单项数组
     */
    List<TradeOrderItemDO> getOrderItemListByOrderIds(Collection<Long> orderIds);

    PageResult<AppTradeOrderPageVO> toPageResult(PageResult<TradeOrderDO> pageResult, boolean isMerchant);

    /**
     * 判断是否为店铺新客
     *
     * @param shopId 店铺编号
     * @param userId 用户编号
     */
    boolean isNewShopCustomer(Long shopId, Long userId);

    /**
     * 获得店铺今日订单数量
     *
     * @param shopId 店铺编号
     * @param type 订单类型
     * @return 订单数量
     */
    int getTodayOrderCount(Long shopId, Integer type);

}
